#include<math.h>
#include<pthread.h>
#include<stdio.h>

int i;
double y;

void *calculoPow1( void *argRes ){
    double *saveVar = (double *)argRes;
    *saveVar = pow( ( 1 + y ), 4 );
    pthread_exit(NULL);
}

void *calculoPow2( void *argRes ){
    double *saveVar = (double *)argRes;
    *saveVar = pow( 2, 2 * i + 3 );
    pthread_exit(NULL);
}

void *calculoPow3( void *argRes ){
    double *saveVar = (double *)argRes;
    *saveVar = pow( y, 2 );
    pthread_exit(NULL);
}

double Borwein( int numIteracoes ){
    void *status;
    double a, aux;
    double argsPow1, argsPow2, argsPow3;
    pthread_t threads[3];

    aux = sqrt(2);
    a = 6 - 4 * aux;
    y = aux - 1;

    for( i = 0; i < numIteracoes; i++ ){
        /*No calculo do y, nao ha operacoes independentes
        que usem funcoes, logo nao compensa usar pthreads*/
        aux = sqrt( sqrt ( ( 1 - pow( y, 4 ) ) ) );
        y = ( 1 - aux ) / ( 1 + aux );

        if( pthread_create( threads + 0, NULL, calculoPow1, (void*)&argsPow1 ) )
            return -1;
        if( pthread_create( threads + 1, NULL, calculoPow2, (void*)&argsPow2 ) )
            return -1;
        if( pthread_create( threads + 2, NULL, calculoPow3, (void*)&argsPow3 ) )
            return -1;

        pthread_join(threads[0], &status);
        pthread_join(threads[1], &status);
        pthread_join(threads[2], &status);

        /*No calculo do a, cada pthread eh responsavel por executar uma das 3 funcoes
        de potenciacao. Isso eh possivel por causa da independencia dessas operacoes
        de potenciacao: O resultado de uma nao eh necessario para executar a outra*/
        if(isinf(argsPow2))
            argsPow2 = 0;

        a = a * argsPow1 - argsPow2 * y * (1 + y + argsPow3);
    }

    return (double)1.0 / a;
}

int main(){
    printf( "%lf", Borwein(1000000));

    return 0;
}
